// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © AlphaNatt

//@version=6
indicator(title='Adaptive Volatility Bands | AlphaNatt', overlay=true, timeframe='', timeframe_gaps=true)

import TradingView/ta/7 as ta

// Color definitions
bullColor = #00F1FF
bearColor = #FF019A

// Adaptive Volatility Bands | AlphaNatt
// Dynamic bands that adapt to market volatility and trend strength

// Core Settings
basis_type = input.string('ALMA', 'Basis Type', options=['SMA', 'EMA', 'ALMA', 'KAMA', 'VWMA'], group='Basis Configuration')
basis_len = input.int(20, 'Basis Length', minval=5, maxval=200, group='Basis Configuration')
alma_offset = input.float(0.85, 'ALMA Offset', minval=0.01, maxval=1, step=0.01, group='Basis Configuration')
alma_sigma = input.float(6, 'ALMA Sigma', minval=1, maxval=50, group='Basis Configuration')

// Calculate Basis Line
kama(src, length) =>
    xvnoise = math.abs(src - src[1])
    nfastend = 0.666
    nslowend = 0.0645
    nsignal = math.abs(src - src[length])
    nnoise = math.sum(xvnoise, length)
    nefratio = nnoise != 0 ? nsignal / nnoise : 0
    nsmooth = math.pow(nefratio * (nfastend - nslowend) + nslowend, 2)
    var nAMA = 0.0
    nAMA := nz(nAMA[1]) + nsmooth * (src - nz(nAMA[1]))
    nAMA

basis = switch basis_type
    'SMA' => ta.sma(close, basis_len)
    'EMA' => ta.ema(close, basis_len)
    'ALMA' => ta.alma(close, basis_len, alma_offset, alma_sigma)
    'KAMA' => kama(close, basis_len)
    'VWMA' => ta.vwma(close, basis_len)
    => ta.sma(close, basis_len)

// Volatility Measurement
vol_method = input.string('ATR', 'Volatility Method', options=['ATR', 'STD', 'RNG'], group='Volatility Settings')
vol_len = input.int(14, 'Volatility Length', minval=5, maxval=50, group='Volatility Settings')
vol_mult = input.float(2.0, 'Band Multiplier', minval=0.5, maxval=5, step=0.1, group='Volatility Settings')

volatility = switch vol_method
    'ATR' => ta.atr(vol_len)
    'STD' => ta.stdev(close, vol_len)
    'RNG' => ta.sma(high - low, vol_len)
    => ta.atr(vol_len)

// Adaptive Multiplier
adapt_enabled = input.bool(true, 'Enable Adaptive Bands', group='Adaptive Settings')
adapt_len = input.int(50, 'Adaptation Period', minval=20, maxval=200, group='Adaptive Settings')

// Calculate trend strength for adaptation
trend_strength = math.abs(ta.linreg(close, adapt_len, 0) - ta.linreg(close, adapt_len, adapt_len-1)) / volatility
normalized_strength = ta.percentile_nearest_rank(trend_strength, adapt_len, 50)

// Adaptive multiplier based on trend strength
adaptive_mult = adapt_enabled ? vol_mult * (1 + normalized_strength / 100) : vol_mult

// Calculate Bands
upper_band = basis + volatility * adaptive_mult
lower_band = basis - volatility * adaptive_mult

// Calculate intermediate bands for gradient effect
upper_mid1 = basis + (volatility * adaptive_mult * 0.75)
upper_mid2 = basis + (volatility * adaptive_mult * 0.5)
upper_mid3 = basis + (volatility * adaptive_mult * 0.25)

lower_mid1 = basis - (volatility * adaptive_mult * 0.25)
lower_mid2 = basis - (volatility * adaptive_mult * 0.5)
lower_mid3 = basis - (volatility * adaptive_mult * 0.75)

// Squeeze Detection
bb_len = input.int(20, 'BB Length', minval=5, maxval=50, group='Squeeze Detection')
bb_mult = input.float(2.0, 'BB Multiplier', minval=1, maxval=4, step=0.1, group='Squeeze Detection')
kc_mult = input.float(1.5, 'KC Multiplier', minval=1, maxval=3, step=0.1, group='Squeeze Detection')

bb_basis = ta.sma(close, bb_len)
bb_dev = bb_mult * ta.stdev(close, bb_len)
kc_range = kc_mult * ta.atr(bb_len)

squeeze = bb_dev < kc_range
expansion = bb_dev > kc_range * 1.5

// Signal Generation
price_above_upper = close > basis
price_below_lower = close < basis
basis_rising = basis > basis[1]
basis_falling = basis < basis[1]

L = price_above_upper and basis_rising
S = price_below_lower and basis_falling

// State Tracking
var vii = 0
if L and not S
    vii := 1
if S
    vii := -1

// Color Logic
basis_color = vii == 1 ? bullColor : vii == -1 ? bearColor : color.gray
band_color = vii == 1 ? color.new(bullColor, 80) : vii == -1 ? color.new(bearColor, 80) : color.new(color.gray, 80)

// Gradient fill colors
fill_color1 = vii == 1 ? color.new(bullColor, 85) : vii == -1 ? color.new(bearColor, 85) : color.new(color.gray, 92)
fill_color2 = vii == 1 ? color.new(bullColor, 88) : vii == -1 ? color.new(bearColor, 88) : color.new(color.gray, 94)
fill_color3 = vii == 1 ? color.new(bullColor, 91) : vii == -1 ? color.new(bearColor, 91) : color.new(color.gray, 96)
fill_color4 = vii == 1 ? color.new(bullColor, 94) : vii == -1 ? color.new(bearColor, 94) : color.new(color.gray, 98)

// Main Plots
basis_plot = plot(basis, 'Basis', color=basis_color, linewidth=2)
upper_plot = plot(upper_band, 'Upper Band', color=band_color, linewidth=1)
lower_plot = plot(lower_band, 'Lower Band', color=band_color, linewidth=1)

// Gradient layer plots (invisible lines for fills)
upper_mid1_plot = plot(upper_mid1, display=display.none)
upper_mid2_plot = plot(upper_mid2, display=display.none)
upper_mid3_plot = plot(upper_mid3, display=display.none)

lower_mid1_plot = plot(lower_mid1, display=display.none)
lower_mid2_plot = plot(lower_mid2, display=display.none)
lower_mid3_plot = plot(lower_mid3, display=display.none)

// Gradient Fills - Upper Band
upper_grad1 = plot(upper_band, "Upper Zone", color.new(bearColor, 0), 1, plot.style_line)
upper_step = (upper_band - basis) / 10

upper_grad2 = plot(upper_band - upper_step, "UG2", color.new(bearColor, 70), 1, plot.style_line)
fill(upper_grad1, upper_grad2, color.new(bearColor, 70))

upper_grad3 = plot(upper_band - upper_step * 2, "UG3", color.new(bearColor, 75), 1, plot.style_line)
fill(upper_grad2, upper_grad3, color.new(bearColor, 75))

upper_grad4 = plot(upper_band - upper_step * 3, "UG4", color.new(bearColor, 80), 1, plot.style_line)
fill(upper_grad3, upper_grad4, color.new(bearColor, 80))

upper_grad5 = plot(upper_band - upper_step * 4, "UG5", color.new(bearColor, 83), 1, plot.style_line)
fill(upper_grad4, upper_grad5, color.new(bearColor, 83))

upper_grad6 = plot(upper_band - upper_step * 5, "UG6", color.new(bearColor, 86), 1, plot.style_line)
fill(upper_grad5, upper_grad6, color.new(bearColor, 86))

upper_grad7 = plot(upper_band - upper_step * 6, "UG7", color.new(bearColor, 89), 1, plot.style_line)
fill(upper_grad6, upper_grad7, color.new(bearColor, 89))

upper_grad8 = plot(upper_band - upper_step * 7, "UG8", color.new(bearColor, 92), 1, plot.style_line)
fill(upper_grad7, upper_grad8, color.new(bearColor, 92))

upper_grad9 = plot(upper_band - upper_step * 8, "UG9", color.new(bearColor, 95), 1, plot.style_line)
fill(upper_grad8, upper_grad9, color.new(bearColor, 95))

upper_grad10 = plot(upper_band - upper_step * 9, "UG10", color.new(bearColor, 98), 1, plot.style_line)
fill(upper_grad9, upper_grad10, color.new(bearColor, 98))

fill(upper_grad10, basis_plot, color.new(bearColor, 99))

// Lower zone gradient
lower_grad1 = plot(lower_band, "Lower Zone", color.new(bullColor, 0), 1, plot.style_line)
lower_step = (basis - lower_band) / 10

lower_grad2 = plot(lower_band + lower_step, "LG2", color.new(bullColor, 70), 1, plot.style_line)
fill(lower_grad1, lower_grad2, color.new(bullColor, 70))

lower_grad3 = plot(lower_band + lower_step * 2, "LG3", color.new(bullColor, 75), 1, plot.style_line)
fill(lower_grad2, lower_grad3, color.new(bullColor, 75))

lower_grad4 = plot(lower_band + lower_step * 3, "LG4", color.new(bullColor, 80), 1, plot.style_line)
fill(lower_grad3, lower_grad4, color.new(bullColor, 80))

lower_grad5 = plot(lower_band + lower_step * 4, "LG5", color.new(bullColor, 83), 1, plot.style_line)
fill(lower_grad4, lower_grad5, color.new(bullColor, 83))

lower_grad6 = plot(lower_band + lower_step * 5, "LG6", color.new(bullColor, 86), 1, plot.style_line)
fill(lower_grad5, lower_grad6, color.new(bullColor, 86))

lower_grad7 = plot(lower_band + lower_step * 6, "LG7", color.new(bullColor, 89), 1, plot.style_line)
fill(lower_grad6, lower_grad7, color.new(bullColor, 89))

lower_grad8 = plot(lower_band + lower_step * 7, "LG8", color.new(bullColor, 92), 1, plot.style_line)
fill(lower_grad7, lower_grad8, color.new(bullColor, 92))

lower_grad9 = plot(lower_band + lower_step * 8, "LG9", color.new(bullColor, 95), 1, plot.style_line)
fill(lower_grad8, lower_grad9, color.new(bullColor, 95))

lower_grad10 = plot(lower_band + lower_step * 9, "LG10", color.new(bullColor, 98), 1, plot.style_line)
fill(lower_grad9, lower_grad10, color.new(bullColor, 98))

fill(lower_grad10, basis_plot, color.new(bullColor, 99))
// Alert Conditions
alertcondition(L, title='AVB Long Signal', message='AVB Long Signal {{exchange}}:{{ticker}}')
alertcondition(S, title='AVB Short Signal', message='AVB Short Signal {{exchange}}:{{ticker}}')
alertcondition(squeeze, title='AVB Squeeze', message='AVB Squeeze {{exchange}}:{{ticker}}')
alertcondition(expansion, title='AVB Expansion', message='AVB Expansion {{exchange}}:{{ticker}}')
alertcondition(price_above_upper, title='AVB Upper Band Touch', message='AVB Upper Band Touch {{exchange}}:{{ticker}}')
alertcondition(price_below_lower, title='AVB Lower Band Touch', message='AVB Lower Band Touch {{exchange}}:{{ticker}}')